/*-------------------------------------------------------------------------
 *
 * large_object.h
 *	  PostgreSQL 大对象的声明。POSTGRES 4.2 支持
 *	  数以亿计的大对象（内部、外部、jaquith、反转）。
 *	  现在我们只支持反转。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/large_object.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef LARGE_OBJECT_H
#define LARGE_OBJECT_H

#include "utils/snapshot.h"


/*----------
 * 当前打开的大对象的数据。
 *
 * id是大对象的逻辑OID
 * snapshot是用于读/写操作的快照
 * subid是打开描述符的子事务（或当前拥有它）
 * offset是在LO内的当前查找偏移量
 * flags包含一些标志位
 *
 * 注意：从v11开始，打开大型对象时会进行权限检查；
 * 因此IFS_RDLOCK/IFS_WRLOCK表示请求了读或写模式
 * 且相应的权限已被检查。
 *
 * 注意：在7.1之前，我们还必须存储对特定大型对象的单独表
 * 和索引的引用。 现在它们都存在于pg_largeobject中
 * 并通过公共关系描述符访问。
 *----------
 */
typedef struct LargeObjectDesc
{
	Oid			id;				/* LO的标识符 */
	Snapshot	snapshot;		/* 要使用的快照 */
	SubTransactionId subid;		/* 拥有的子事务ID */
	uint64		offset;			
/* 当前查找指针 */
	int			flags;			/* 查看下面的标志位 */

/* 标志中的位: */
#define IFS_RDLOCK		(1 << 0)	/* LO已打开以进行读取 */
#define IFS_WRLOCK		(1 << 1)	/* LO已打开以进行写入 */

} LargeObjectDesc;


/*
 * 大对象的每个“页面”（元组）可以容纳这么多数据
 *
 * 我们可以将其设置为高达BLCKSZ减去一些开销，但似乎
 * 更好将其设为一个较小的值，以便在更新页面元组时不会占用太多空间。
 * 请注意，该值故意选择得足够大，以触发元组压缩器，从而
 * 我们将尝试内联压缩页面元组。 （但它们不会被移动，除非
 * 用户为pg_largeobject创建了示例表……）
 *
 * 此外，将页面大小设置为2的幂的做法似乎是明智的，
 * 因为客户端通常会编写为以2的幂块发送数据。
 * 这避免了因部分页面写入而导致的不必要的元组更新。
 *
 * 注意：更改LOBLKSIZE需要执行initdb。
 */
#define LOBLKSIZE		(BLCKSZ / 4)

/*
 * 大对象的最大字节长度。要增大此值，我们需要
 * 扩展pg_largeobject.pageno以及各种内部变量。
 */
#define MAX_LARGE_OBJECT_SIZE	((int64) INT_MAX * LOBLKSIZE)


/*
 * GUC：向后兼容标志以抑制 LO 权限检查
 */
extern PGDLLIMPORT bool lo_compat_privileges;

/*
 * 函数定义...
 */

/* inv_api.c中的反转相关内容 */
extern void close_lo_relation(bool isCommit);
extern Oid	inv_create(Oid lobjId);
extern LargeObjectDesc *inv_open(Oid lobjId, int flags, MemoryContext mcxt);
extern void inv_close(LargeObjectDesc *obj_desc);
extern int	inv_drop(Oid lobjId);
extern int64 inv_seek(LargeObjectDesc *obj_desc, int64 offset, int whence);
extern int64 inv_tell(LargeObjectDesc *obj_desc);
extern int	inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes);
extern int	inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes);
extern void inv_truncate(LargeObjectDesc *obj_desc, int64 len);

#endif							/* LARGE_OBJECT_H */
